import * as fs from 'fs';
import { ByteBuffer } from '../lib/ByteBuffer';
'use strict';

type Selector<$> = { $: Record<keyof $, any | null> } & { dispatch(str: string): void, dump :any, dirty: boolean, packageName: string, list: string[] };
type PanelThis = Selector<typeof $> & typeof methods;

export const template = `
<ui-prop type="dump" id="packageprop">
    <ui-label slot="label" value="fgui二进制文件"></ui-label>
    <ui-asset slot="content" droppable="cc.BufferAsset" id="package"></ui-asset>
</ui-prop>
<ui-prop type="dump" id="packagename"></ui-prop>
<ui-prop type="dump" id="itemnameprop">
    <ui-label slot="label" value="渲染组件"></ui-label>
    <ui-select slot="content" id="itemname"></ui-select>
</ui-prop>
<ui-prop type="dump" id="clickable"></ui-prop>
`;

export const $ = {
    packageprop: '#packageprop',
    package: '#package',
    packagename: '#packagename',
    itemname: '#itemname',
    itemnameprop: '#itemnameprop',
    clickable: '#clickable',
};

export function update(this: PanelThis, dump: any) {
    if (this.dirty) {
        this.dirty = false;
        this.refresh(dump.value.package.value.uuid);
    }
    this.dump = dump;

    this.list = this.list || [];
    let optionsHtml = '';
    this.list.forEach((name, index) => {
        optionsHtml += `<option value="${index}">${name}</option>`;
    });
    this.$.itemname.innerHTML = optionsHtml;

    this.$.packageprop.dump = dump.value.package;
    this.$.package.value = dump.value.package.value.uuid;
    this.$.packagename.render(dump.value.packageName);
    this.$.itemnameprop.dump = dump.value.itemName;
    const index = this.list.indexOf(dump.value.itemName.value);
    this.$.itemname.value = index;
    this.$.clickable.render(dump.value._clickable);
}
export function ready(this: PanelThis) {
    this.dirty = true;

    this.$.package.addEventListener('change', this.onPackageChange.bind(this));
    this.$.package.addEventListener('confirm', (e: any) => {
        this.dump.value.package.value.uuid = e.target.value;
        this.$.packageprop.dispatch('change-dump');
    });
    this.$.itemname.addEventListener('confirm', (e: any) => {
        const index = Number(e.target.value);
        this.dump.value.itemName.value = this.list[Number(e.target.value)];
        this.$.itemname.value = index;
        this.$.itemnameprop.dispatch('change-dump');
    });
}

function readFileBuffer(file: string): Promise<ArrayBuffer> {
    return new Promise((resolve, reject) => {
        fs.readFile(file, (err: any, data: any) => {
            if (err) {
                reject(err);
            } else {
                resolve(data.buffer);
            }
        });
    });
}

export const methods = {
    onPackageChange(event: any) {
        console.log('onPackgeChange ::: ', event.target);
        const panel : PanelThis = this as PanelThis;
        panel.dump.value.package.value.uuid = event.target.value;
        this.refresh(event.target.value);
    },

    async refresh(value: any) {
        console.log('refresh >>>>>>>>>>>>>. ', value);
        const panel : PanelThis = this as PanelThis;
        let assetPath: string|null = null;
        if (value && value.length > 0) {
            assetPath = await await Editor.Message.request('asset-db', 'query-path', value);
        }
        if (assetPath && assetPath.length > 0 && fs.existsSync(assetPath)) {
            const array = await readFileBuffer(assetPath);
            let buffer = new ByteBuffer(array, 0, array.byteLength);
            if (buffer.readUint() != 0x46475549)
                throw new Error('FairyGUI: old package format found in \'' + assetPath + '\'');

            buffer.version = buffer.readInt();
            let ver2: boolean = buffer.version >= 2;
            let compressed: boolean = buffer.readBool();
            buffer.readString();
            const packageName = buffer.readString();
            buffer.skip(20);

            let indexTablePos: number = buffer.position;
            let cnt: number;
            let i: number;
            buffer.seek(indexTablePos, 4);

            cnt = buffer.readInt();
            let stringTable: Array<string> = new Array<string>(cnt);
            buffer.stringTable = stringTable;

            for (i = 0; i < cnt; i++)
                stringTable[i] = buffer.readString();

            if (buffer.seek(indexTablePos, 5)) {
                cnt = buffer.readInt();
                for (i = 0; i < cnt; i++) {
                    let index = buffer.readUshort();
                    let len = buffer.readInt();
                    stringTable[index] = buffer.readString(len);
                }
            }

            buffer.seek(indexTablePos, 0);
            cnt = buffer.readShort();
            for (i = 0; i < cnt; i++) {
                // this._dependencies.push({ id: buffer.readS(), name: buffer.readS() });
                buffer.readS();
                buffer.readS();
            }

            if (ver2) {
                cnt = buffer.readShort();
                if (cnt > 0) {
                    // this._branches = buffer.readSArray(cnt);
                    buffer.readSArray(cnt);
                }
            }

            buffer.seek(indexTablePos, 1);

            let list: string[] = [];
            cnt = buffer.readShort();
            let nextPos = buffer.position;
            for (i = 0; i < cnt; i++) {
                buffer.position = nextPos;
                nextPos = buffer.readInt();
                nextPos += buffer.position;

                const type = buffer.readByte();
                if (type != 3) continue
                // pi.id = buffer.readS();
                buffer.readS();
                const name = buffer.readS();
                buffer.readS(); //path
                // pi.file = buffer.readS();
                buffer.readS();
                const exported = buffer.readBool();//exported
                if (!exported) continue;
                list.push(name);
            }

            if (panel.dump)
                panel.dump.value.packageName.value = packageName;
            panel.packageName = packageName;
            panel.$.packagename.dispatch('change-dump');
            panel.list = list;
        } else {
            if (panel.dump && panel.dump.value.packageName)
                panel.dump.value.packageName.value = '';
            panel.packageName = '';
            panel.$.packagename.dispatch('change-dump');
            panel.list = [];
        }
    },
};